package org.framework.config;

import org.framework.annotation.MessageQueueScan;
import org.framework.annotation.RabbitSettingProducer;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.context.expression.StandardBeanExpressionResolver;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 * @ClassName RabbitMqProducerRegistrar
 * @Description 注册器
 * @Author RayLiang
 * @Date 2022/12/12 15:16
 * @Version 1.0
 **/
public class RabbitMqProducerRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware, EnvironmentAware, BeanClassLoaderAware {

    private BeanFactory beanFactory;

    private Environment environment;

    private BeanExpressionResolver resolver = new StandardBeanExpressionResolver();

    private BeanExpressionContext expressionContext;

    private ClassLoader beanClassLoader;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(MessageQueueScan.class.getName());
        ClassPathMessageQueueScanner classPathMessageQueueScanner = new ClassPathMessageQueueScanner(registry, this.beanFactory, this.environment, this.resolver, this.expressionContext, this.beanClassLoader);
        classPathMessageQueueScanner.addIncludeFilter(new AnnotationTypeFilter(RabbitSettingProducer.class));
        Object value = resolveExpression(annotationAttributes.get("value").toString());
        if (!StringUtils.isEmpty(value.toString())) {
            String[] splitvalue = value.toString().split("[;,]");
            classPathMessageQueueScanner.scan(splitvalue);
        }
    }


    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
        if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
            ConfigurableListableBeanFactory bf = (ConfigurableListableBeanFactory) beanFactory;
            bf.addEmbeddedValueResolver(strVal -> this.environment.resolvePlaceholders(strVal));
            this.resolver = ((ConfigurableListableBeanFactory) beanFactory).getBeanExpressionResolver();
            this.expressionContext = new BeanExpressionContext((ConfigurableListableBeanFactory) beanFactory, null);
        }
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.beanClassLoader = classLoader;
    }


    private Object resolveExpression(String value) {
        String resolvedValue = resolve(value);

        return this.resolver.evaluate(resolvedValue, this.expressionContext);
    }

    private String resolve(String value) {
        if (this.beanFactory != null && this.beanFactory instanceof ConfigurableBeanFactory) {
            return ((ConfigurableBeanFactory) this.beanFactory).resolveEmbeddedValue(value);
        }
        return value;
    }

}